import java.awt.Color;
import java.awt.Graphics;
import java.util.Map;

import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.events.ServerMessageEvent;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.event.listeners.ServerMessageListener;
import com.speljohan.rsbot.script.Constants;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.wrappers.RSInterface;
import com.speljohan.rsbot.script.wrappers.RSObject;
import com.speljohan.rsbot.script.wrappers.RSTile;

public class BarbCoal extends Script implements ServerMessageListener,
		PaintListener {

	private final long startTime = System.currentTimeMillis();
	private final RSTile[] path = { new RSTile(3093, 3491),
			new RSTile(3080, 3483), new RSTile(3080, 3472),
			new RSTile(3087, 3460), new RSTile(3089, 3445),
			new RSTile(3090, 3431), new RSTile(3083, 3423) };
	private int mined = 0, loads = 0;
	private final int[] rocks = { 11930, 11931, 11932 }, picks = { 1265, 1267,
			1269, 1273, 1271, 1275 }, empty = { 11553, 11554, 11552 };
	private final RSTile bankTile = path[0], coalTile = path[path.length - 1];
	private RSTile currentTile = new RSTile(3081, 3422);
	private final int wait1 = 300, wait2 = 500, bankID = 26972;
	private String doing;
	private boolean isMining;
	private int currentRock = rocks[0];

	private boolean findAllEmpty() {
		for (final int id : empty) {
			if (findObject(id) == null) {
				return false;
			}
		}
		return true;
	}

	@Override
	public String getAuthor() {
		return "Fusion89k";
	}

	@Override
	public String getName() {
		return "Barbarian Coal Miner";
	}

	@Override
	public String getScriptCategory() {
		return "Mining";
	}

	@Override
	public String getScriptDescription() {
		return "<html>\n" + "<head></head>\n"
				+ "<body bgcolor=\"black\" text=\"white\">\n" + "<center>"
				+ "<h2>" + getName() + "</h2>" + "</center>\n"
				+ "<b>Author:</b> " + getAuthor() + "<br />"
				+ "<b>Version:</b> " + getVersion()
				+ "<BR>Have pickAxe in inventory or equipped" + "</body>\n"
				+ "</html>";
	}

	@Override
	public double getVersion() {
		return 1.3;
	}

	private boolean isCarryingItemCustom(final int... items) {
		for (final int i : items) {
			if (getInventoryCount(i) > 0) {
				return true;
			}
		}
		for (final int item : items) {
			if (getEquipmentInterface().getInventoryItemCount(item) > 0) {
				return true;
			}
		}
		return false;
	}

	private boolean isMoving() {
		if (!getMyPlayer().isMoving()) {
			return false;
		}
		if (!locate().equals(path[0]) || !locate().equals(path[1])
				|| !locate().equals(path[path.length - 1])
				|| !locate().equals(path[path.length - 2])) {
			if (distanceTo(getDestination()) < 5) {
				return false;
			}
		}
		return true;
	}

	private RSTile locate() {
		RSTile min = path[0];
		for (int i = 1; i < path.length; i++) {
			if (distanceTo(path[i]) < distanceTo(min)) {
				min = path[i];
			}
		}
		return min;
	}

	@Override
	public int loop() {
		setCompass('w');
		setCameraAltitude(true);
		if (!isCarryingItemCustom(picks) && isLoggedIn()) {
			log("No PickAxe");
			stopAllScripts();
		}
		if (isMoving()) {
			return random(wait1, wait2);
		}
		if (getMyPlayer().isInCombat()) {
			doing = "Running from Combat";
			setRun(true);
			walk(true);
			return random(wait1, wait2);
		}
		if (isMining && getMyPlayer().getAnimation() == -1) {
			isMining = false;
		}
		if (!isInventoryFull()) {
			if (isMining) {// Smoking rocks got some help from: Tenac
				try {
					final int curID = getObjectAt(currentTile).getID();
					if (curID != currentRock) {
						isMining = false;
						mine();
					}
				} catch (final Exception e) {
					log("Smoking detection error");
				}
				return random(wait1, wait2);
			}
			if (distanceTo(coalTile) > 4) {
				doing = "Walking to Coal";
				return walk(false);
			}
			doing = "Finding Coal";
			final RSObject rock = findObject(rocks);
			if (rock == null) {
				doing = "Waiting for Coal";
				randomStuff();
				return random(wait1, wait2);
			}
			mine();
		} else {
			if (distanceTo(bankTile) > 4) {
				doing = "Walking to Bank";
				return walk(true);
			}
			if (!RSInterface.getInterface(Constants.INTERFACE_BANK).isValid()) {
				doing = "Finding Bank";
				final RSObject booth = findObject(bankID);
				if (booth == null) {
					return random(wait1, wait2);
				}
				if (!tileOnScreen(booth.getLocation())) {
					walkTileMM(booth.getLocation());
					return random(wait1, wait2);
				}
				atObject(booth, "Use-Quickly");
				return random(wait1, wait2);
			}
			if (RSInterface.getInterface(Constants.INTERFACE_BANK).isValid()) {
				doing = "Depositing";
				bank.depositAllExcept(picks);
				loads++;
				bank.close();
			}
		}
		if (getEnergy() > random(50, 100)) {
			setRun(true);
		}
		return random(wait1, wait2);
	}

	private void mine() {
		final RSObject rock = findObject(rocks);
		if (rock == null && !findAllEmpty()) {
			atTile(randomTile(getMyPlayer().getLocation()), "walk");
			isMining = false;
			return;
		}
		doing = "Mining Coal";
		atObject(rock, "Mine");
		isMining = true;
		currentTile = rock.getLocation();
		currentRock = rock.getID();
		openTab(Constants.TAB_INVENTORY);
	}

	@Override
	public void onFinish() {
		Bot.getEventManager().removeListener(PaintListener.class, this);
	}

	public void onRepaint(final Graphics g) {
		if (isLoggedIn()) {
			long millis = System.currentTimeMillis() - startTime;
			final long hours = millis / (1000 * 60 * 60);
			millis -= hours * 1000 * 60 * 60;
			final long minutes = millis / (1000 * 60);
			millis -= minutes * 1000 * 60;
			final long seconds = millis / 1000;
			final int topX = 515 - 173, topY = 337 - 80, x = topX + 5;
			int y = topY + 5;
			g.setColor(new Color(0, 100, 0, 100));
			g.fill3DRect(topX, topY, 515 - topX, 337 - topY, true);
			g.setColor(Color.green);
			g.drawString("Runtime: " + hours + "h " + minutes + "min "
					+ seconds + "sec.", x, y += 15);
			g.drawString("Ore Mined: " + Integer.toString(mined), x, y += 15);
			g.drawString("Loads Done: " + loads, x, y += 15);
			g.drawString("Status: " + doing, x, y += 15);
		}
	}

	@Override
	public boolean onStart(final Map<String, String> args) {
		return true;
	}

	private void randomStuff() {
		final int temp = random(1, 50);
		switch (temp) {
		case 3:
		case 4:
			moveMouse(random(150, 450), random(100, 300));
			break;
		case 2:
			openTab(Constants.TAB_STATS);
			final RSTile mining = randomTile(new RSTile(680, 230));
			moveMouse(mining.getX(), mining.getY());
			break;
		case 6:
			openTab(random(0, 13));
			break;
		}
	}

	private RSTile randomTile(final RSTile tile) {
		return new RSTile(random(tile.getX() - 2, tile.getX() + 2), random(tile
				.getY() - 2, tile.getY() + 2));
	}

	public void serverMessageRecieved(final ServerMessageEvent e) {
		final String word = e.getMessage().toLowerCase();
		if (word.contains("coal")) {
			mined++;
			isMining = false;
		}
	}

	private int walk(final boolean toBank) {
		final RSTile start = locate();
		int loc = 0;
		for (int i = 0; i < path.length; i++) {
			if (start.equals(path[i])) {
				loc = i;
				break;
			}
		}
		if (toBank) {
			if (loc == 0) {
				return random(wait1, wait2);
			}
			walkTileMM(randomTile(path[loc - 1]));
		} else {
			if (loc == path.length - 1) {
				walkTileMM(coalTile);
			} else {
				walkTileMM(randomTile(path[loc + 1]));
			}
		}
		return random(wait1, wait2);
	}
}